use std::sync::Arc;
use std::time::Duration;
use anyhow::Result;
use async_trait::async_trait;
use tokio::time::sleep;
use tracing::Level;

use protoactor_rs::actor::{Actor, ActorContext, ActorError, Props};
use protoactor_rs::system::ActorSystem;
use protoactor_rs::metrics::{self, MetricsMiddleware};

// 工作Actor
struct WorkerActor {
    id: String,
    work_time: Duration,
}

impl WorkerActor {
    fn new(id: String, work_time: Duration) -> Self {
        Self { id, work_time }
    }
}

#[async_trait]
impl Actor for WorkerActor {
    type Context = protoactor_rs::actor::DefaultActorContext;
    
    async fn receive(&self, ctx: &mut Self::Context, msg: Box<dyn std::any::Any + Send>) -> Result<(), ActorError> {
        if let Some(work) = msg.downcast_ref::<DoWork>() {
            println!("[{}] Received work request: {}", self.id, work.0);
            
            // 模拟工作耗时
            sleep(self.work_time).await;
            
            // 随机生成错误
            if rand::random::<f32>() < 0.1 {
                return Err(ActorError::ActorFailure("Random work failure".to_string()));
            }
            
            ctx.respond(WorkComplete(work.0));
        }
        Ok(())
    }
    
    async fn started(&self, _ctx: &mut Self::Context) -> Result<(), ActorError> {
        println!("[{}] Worker started", self.id);
        metrics::get_metrics().record_actor_start(&self.id);
        Ok(())
    }
    
    async fn stopping(&self, _ctx: &mut Self::Context) -> Result<(), ActorError> {
        println!("[{}] Worker stopping", self.id);
        metrics::get_metrics().record_actor_stop(&self.id);
        Ok(())
    }
}

#[derive(Debug)]
struct DoWork(usize);

#[derive(Debug)]
struct WorkComplete(usize);

#[tokio::main]
async fn main() -> Result<()> {
    // 初始化日志
    tracing_subscriber::fmt()
        .with_max_level(Level::DEBUG)
        .init();
    
    // 创建Actor系统
    let system = Arc::new(ActorSystem::new()?);
    
    // 创建带有指标中间件的Props
    let worker_props = Props::new(Box::new(|| {
        Box::new(WorkerActor::new(
            "worker_1".to_string(),
            Duration::from_millis(100),
        ))
    }))
    .with_middleware(MetricsMiddleware::new());
    
    // 启动worker
    let worker_pid = system.spawn(worker_props).await?;
    
    // 发送一些工作
    for i in 0..10 {
        match system.request::<WorkComplete>(&worker_pid, DoWork(i), Duration::from_secs(1)).await {
            Ok(_) => println!("Work {} completed successfully", i),
            Err(e) => {
                println!("Work {} failed: {}", i, e);
                metrics::get_metrics().record_error("work_failed");
            }
        }
    }
    
    // 打印指标
    println!("\nMetrics:");
    println!("{}", metrics::export_metrics());
    
    // 停止worker
    system.stop(&worker_pid).await?;
    
    Ok(())
} 